package com.example.base_model.room.type_converter

import android.net.Uri
import androidx.room.TypeConverter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types.newParameterizedType
import java.time.Instant

/**
 * @Author jiangKunKun
 * @CreateDate 2025/8/19
 * @Description Room 数据库类型转换器，用于将自定义类型转换为 Room 可支持的类型。
 * @SpittingGrooves
 */
class ProfileConverters {
    /**
     * Moshi 实例，用于 JSON 序列化和反序列化
     */
    private val moshi = Moshi.Builder().build()
    /**
     * 定义 Map<String, Any> 的参数化类型，用于 Moshi 适配器
     */
    private val mapType = newParameterizedType(Map::class.java, String::class.java, Any::class.java)
    /**
     * 创建 Map<String, Any> 类型的 JSON 适配器
     */
    private val jsonAdapter = moshi.adapter<Map<String, Any>>(mapType)

    /**
     * 将 Uri 对象转换为 String。
     * Room 数据库不支持直接存储 Uri 对象，需要转换为 String。
     * @param uri 待转换的 Uri 对象。
     * @return 转换后的 String 形式的 Uri，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun uriToString(uri: Uri?): String? = uri?.toString()

    /**
     * 将 String 转换为 Uri 对象。
     * 从 Room 数据库中读取 String 后，将其转换回 Uri 对象。
     * @param string 待转换的 String 形式的 Uri。
     * @return 转换后的 Uri 对象，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun stringToUri(string: String?): Uri? = string?.let { Uri.parse(it) }

    /**
     * 将 Instant 对象转换为 Long (时间戳)。
     * Room 数据库不支持直接存储 Instant 对象，需要转换为 Long 类型的时间戳。
     * @param instant 待转换的 Instant 对象。
     * @return 转换后的 Long 类型的时间戳（Epoch 毫秒），如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun instantToLong(instant: Instant?): Long? = instant?.toEpochMilli()

    /**
     * 将 Long (时间戳) 转换为 Instant 对象。
     * 从 Room 数据库中读取 Long 类型的时间戳后，将其转换回 Instant 对象。
     * @param long 待转换的 Long 类型的时间戳（Epoch 毫秒）。
     * @return 转换后的 Instant 对象，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun longToInstant(long: Long?): Instant? = long?.let { Instant.ofEpochMilli(it) }

    /**
     * 将 Preference 枚举对象转换为 String。
     * Room 数据库不支持直接存储枚举对象，需要转换为 String。
     * @param preference 待转换的 Preference 枚举对象。
     * @return 转换后的 String 形式的枚举名称，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun preferenceToString(preference: Preference?): String? = preference?.name

    /**
     * 将 String 转换为 Preference 枚举对象。
     * 从 Room 数据库中读取 String 后，将其转换回 Preference 枚举对象。
     * @param string 待转换的 String 形式的枚举名称。
     * @return 转换后的 Preference 枚举对象，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun stringToPreference(string: String?): Preference? =
        string?.let { Preference.valueOf(it) }

    /**
     * 将 Map<String, Any> 对象转换为 JSON 字符串。
     * Room 数据库不支持直接存储 Map 对象，需要转换为 JSON 字符串。
     * @param map 待转换的 Map<String, Any> 对象。
     * @return 转换后的 JSON 字符串，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun mapToJson(map: Map<String, Any>?): String? =
        map?.let { jsonAdapter.toJson(it) }

    /**
     * 将 JSON 字符串转换为 Map<String, Any> 对象。
     * 从 Room 数据库中读取 JSON 字符串后，将其转换回 Map<String, Any> 对象。
     * @param json 待转换的 JSON 字符串。
     * @return 转换后的 Map<String, Any> 对象，如果输入为 null 则返回 null。
     */
    @TypeConverter
    fun jsonToMap(json: String?): Map<String, Any>? =
        json?.let { jsonAdapter.fromJson(it) }
}

/**
 * 用户偏好设置的枚举类。
 */
enum class Preference {
    LIGHT,   // 亮色主题
    DARK,    // 暗色主题
    SYSTEM   // 跟随系统主题
}